﻿using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using PersonalWebsite.Domain.Abstract.Entities;

namespace PersonalWebsite.Domain.Abstract.DBContext.Interceptors
{
    /// <summary>
    /// 发布事件的拦截器
    /// </summary>
    public sealed class PublishDomainEventsInterceptor : SaveChangesInterceptor
    {
        private readonly IPublisher _publisher;

        public PublishDomainEventsInterceptor(IPublisher publisher)
        {
            _publisher = publisher;
        }

        public override async ValueTask<int> SavedChangesAsync(SaveChangesCompletedEventData eventData, int result, CancellationToken cancellationToken = default)
        {
            if(eventData.Context!=null)
               await PublishDomainEventsaAsync(eventData.Context);

            return result;
        }

        private async Task PublishDomainEventsaAsync(DbContext dbContext)
        {
            var domainEntities = dbContext.ChangeTracker
               .Entries<Entity>()
               .Where(c => c.Entity.DomainEvents != null && c.Entity.DomainEvents.Any());

            if (domainEntities != null && domainEntities.Any())
            {
                var domainEvents = domainEntities.SelectMany(c => c.Entity.DomainEvents);

                foreach (var domainEvent in domainEvents)
                {
                    _publisher.Publish(domainEvent);
                }

                domainEntities.ToList().ForEach(c => c.Entity.ClearDomainEvent());
            }
        }
    }
}
